package com.hongyi.common.web.filter;

import com.hongyi.common.framework.constant.Constants;
import com.hongyi.common.framework.utils.http.HttpHelper;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 构建可重复读取inputStream的request
 *
 * <p>作用:请求体已经被读取一次，后续的读取操作仍然可以获取到请求体的内容，避免了请求体只能读取一次的问题</p>
 * @author DingHao
 */
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
    //字节数组，用于存储请求体的内容
    private final byte[] body;

    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
    {
        //调用父类的构造函数，将原始的 HttpServletRequest 对象传递给 HttpServletRequestWrapper
        super(request);
        //设置请求和响应的字符编码为 UTF-8
        request.setCharacterEncoding(Constants.UTF8);
        response.setCharacterEncoding(Constants.UTF8);
        //读取请求体的内容，并将其转换为字节数组存储在 body 中
        body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
    }

    /**
     * 读取请求体的内容,返回一个BufferedReader
     */
    @Override
    public BufferedReader getReader() throws IOException
    {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException
    {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream()
        {
            @Override
            public int read() throws IOException
            {
                return bais.read();
            }

            @Override
            public int available() throws IOException
            {
                return body.length;
            }

            @Override
            public boolean isFinished()
            {
                return false;
            }

            @Override
            public boolean isReady()
            {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener)
            {

            }
        };
    }
}
